package com.ciei.dpagm.controller;

import com.alibaba.fastjson.JSONObject;
import com.ciei.dpagm.common.controller.BaseController;
import com.ciei.dpagm.common.enums.ErrorCodeEnum;
import com.ciei.dpagm.common.enums.LogTypeEnum;
import com.ciei.dpagm.entity.Role;
import com.ciei.dpagm.entity.Users;
import com.ciei.dpagm.service.*;
import com.ciei.dpagm.util.APP;
import com.ciei.dpagm.util.JsonUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.sql.Timestamp;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Controller
public class LoginController extends BaseController {

	@Autowired
	private UsersService usersService;
	@Autowired
	private LogService logService;
	@Autowired
	private RightService rightService;
	@Autowired
	private RoleService roleService;


	/**
	 * 通过用户名和密码登录
	 *
	 * @return
	 */
	@RequestMapping("/login")
	public String loginPage() {
		return "login";
	}

	/**
	 * 技术管理员和区域管理员登录界面
	 *
	 * @return
	 */
	@RequestMapping("/loginTechnician")
	public String loginTechnician() {
		return "loginTechnician";
	}

	/**
	 * 普通用户登录，使用用户名和密码登录
	 *
	 * @param loginName
	 * @param password
	 * @return
	 */
	@RequestMapping("/login/check")
	@ResponseBody
	public JSONObject loginCheck(String loginName, String password) {
		JSONObject jsonObject;
		try {
			if(StringUtils.isBlank(loginName)){
				return JsonUtil.getFail(ErrorCodeEnum.DATA_NOT_FOUND, "登录名不能为空");
			}
			if(StringUtils.isBlank(password)){
				return JsonUtil.getFail(ErrorCodeEnum.DATA_NOT_FOUND, "密码不能为空");
			}
			UsernamePasswordToken token = new UsernamePasswordToken(loginName, password);
			Subject subject = SecurityUtils.getSubject();
			Users existUser = usersService.loadByUsernameAndPassword(loginName, password);
			if (existUser == null) {
				logService.addLog(LogTypeEnum.LOGIN_LOGOUT, "用户名或密码错误", null, null, loginName);
				return JsonUtil.getFail(ErrorCodeEnum.DATA_NOT_FOUND, "用户名或密码错误");
			}
			List<Role> enableRoleList = null;
			if (!usersService.isAdmin(existUser.getUserId())) {
				enableRoleList = roleService.getEnableRoleList(existUser.getUserId());
				if (enableRoleList == null || enableRoleList.isEmpty()) {
					return JsonUtil.getFail(ErrorCodeEnum.INSUFFICIENT_PERMISSIONS, "该用户未分配角色或角色已停用,请联系管理员!");
				}
			}
			subject.login(token);

			jsonObject = JsonUtil.getSuccess("登录成功！");
			JSONObject userJson = (JSONObject) JSONObject.toJSON(existUser);
			if (usersService.isAdmin(existUser.getUserId())) {
				userJson.put("roleIds", Collections.singletonList(Role.SYSTEM_ROLE_ID_ADMIN));
				userJson.put("menus", rightService.buildRightMenuTree(rightService.findAllMenu(), 0));
				userJson.put("permissions", rightService.findAllPermission());
			} else {
				if (enableRoleList != null && !enableRoleList.isEmpty()) {
					List<Integer> rolesIdList = enableRoleList.stream().map(Role::getRoleId).collect(Collectors.toList());
					userJson.put("roleIds", rolesIdList);
					userJson.put("menus", rightService.loadRightMenuTreeByRoleId(rolesIdList));
					userJson.put("permissions", rightService.findPermission(rolesIdList));
				} else {
					return JsonUtil.getFail(ErrorCodeEnum.INSUFFICIENT_PERMISSIONS, "用户权限查询失败");
				}
			}
			jsonObject.put("user", userJson);
			logService.addLog(LogTypeEnum.LOGIN_LOGOUT, "登录成功", null, null, loginName);
			// 更新最后登录时间
			Users updateTimeEntity = new Users();
			updateTimeEntity.setUserId(existUser.getUserId());
			updateTimeEntity.setLastLoginTime(new Timestamp(System.currentTimeMillis()));
			usersService.updateById(updateTimeEntity);
			return jsonObject;
		} catch (AuthenticationException e) {
			// 可能用户名密码不正确、账号被锁定等引起的错误
			logService.addLog(LogTypeEnum.LOGIN_LOGOUT, "登录失败", null, null, loginName);
			e.printStackTrace();
			return JsonUtil.getFail(e.getMessage());
		} catch (Exception e) {
			logService.addLog(LogTypeEnum.LOGIN_LOGOUT, "未知异常", null, null, loginName);
			e.printStackTrace();
			return JsonUtil.getFail("登陆失败！未知异常！");
		}
	}


	@RequestMapping("/logout")
	@ResponseBody
	public JSONObject logout() {
		Subject subject = SecurityUtils.getSubject();
		Users currentUser = (Users)subject.getPrincipal();
		if (subject.isAuthenticated()) {
			subject.logout(); // session 会销毁，在SessionListener监听session销毁，清理权限缓存
			logService.addLog(LogTypeEnum.LOGIN_LOGOUT, "退出登录",null, null, null, currentUser);
			return JsonUtil.getSuccess("OK");
		}else {
			return JsonUtil.getFail(ErrorCodeEnum.NO_AUTHORIZATION);
		}
	}

    @RequestMapping("/login/getInfo")
    @ResponseBody
    public JSONObject getInfo() {
		Users user = (Users) SecurityUtils.getSubject().getPrincipal();
        JSONObject resultJson = new JSONObject();
        List<Integer> rolesIdList;
        if (usersService.isAdmin(user.getUserId())) {
            rolesIdList = Collections.singletonList(Role.SYSTEM_ROLE_ID_ADMIN);
            resultJson.put("roles", rolesIdList);
            resultJson.put("menus", rightService.buildRightMenuTree(rightService.findAllMenu(), 0));
            resultJson.put("permissions", rightService.findAllPermission());
        } else {
            List<Role> enableRoleList = roleService.getEnableRoleList(user.getUserId());
            if (enableRoleList != null && !enableRoleList.isEmpty()) {
                rolesIdList = enableRoleList.stream().map(Role::getRoleId).collect(Collectors.toList());
                resultJson.put("roles", rolesIdList);
                resultJson.put("menus", rightService.loadRightMenuTreeByRoleId(rolesIdList));
                resultJson.put("permissions", rightService.findPermission(rolesIdList));
            } else {
                return JsonUtil.getFail(ErrorCodeEnum.INSUFFICIENT_PERMISSIONS, "该用户未分配角色或角色已停用,请联系管理员!");
            }
        }
        resultJson.put("user", user);
        return JsonUtil.getSuccess("获取成功").fluentPut(APP.DATA, resultJson);
    }

}
